package snaptest.core;

import org.junit.ComparisonFailure;
import org.junit.runners.model.Statement;

import snaptest.core.exception.ReferenceFileNotFound;

public class SnapTestMethodHandler extends Statement {

	private final MethodInvoker methodInvoker;
	private final ReferenceFileLocator referenceLocator;

	public SnapTestMethodHandler(MethodInvoker invocationAgent, ReferenceFileLocator referenceLocator) {
		this.methodInvoker = invocationAgent;
		this.referenceLocator = referenceLocator;
	}

	@Override
	public void evaluate() throws Throwable {
		Object returnValue = methodInvoker.invokeExplosively();
		String actualString = returnValue == null ? null : returnValue.toString();
		if (referenceLocator.referenceExist()) {
			String referenceString = referenceLocator.loadReference();
			if (!isEqual(referenceString, actualString)) {
				referenceLocator.saveActual(actualString);
				throwComparisonFailure(actualString, referenceString);
			}
		} else {
			referenceLocator.saveActual(actualString);
			throwReferenceFileNotFoundException();
		}
	}

	private void throwComparisonFailure(String actualString, String referenceString) throws ComparisonFailure {
		throw new ComparisonFailure("Actual result does not match expectation.", referenceString, actualString);
	}

	private void throwReferenceFileNotFoundException() {
		throw new ReferenceFileNotFound(referenceLocator.getFileName());
	}
	
	private static boolean isEqual(String s1, String s2) {
		return s1 == s2 || (s1 != null && s1.equals(s2));
	}
}
